package cn.edu.dutir.utility;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * An <code>ObjectToSet</code> provides a {@link java.util.Map} from
 * arbitrary objects to objects of class {@link java.util.Set}.
 * In addition to methods inherited from {@link java.util.Map},
 * there are methods to add members to a set value and get
 * set values directly.
 *
 */
public class ObjectToSet<K, V> extends HashMap<K, Set<V>> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -5375402479961006051L;

    /**
     * Construct a new object to set mapping.
     */
	public ObjectToSet() {
		super();
	}

    /**
     * Add a member to the value of the set mapped to by
     * the specified key.
     *
     * @param key Key whose set value will have the object.
     * @param value Object to add to the value of the key.
     */
	public void addMember(K key, V value) {
		Set<V> oldSet = get(key);
		if (oldSet != null) {
			oldSet.add(value);
		} else {
			Set<V> newSet = new HashSet<V>();
			newSet.add(value);
			put(key, newSet);
		}
	}

    /**
     * Adds a set of members to the value of the set mapped to by
     * the specified key.
     *
     * @param key Key whose set value will have the object.
     * @param values Values to add to the set picked out by the key.
     */
	public void addMemebers(K key, Set<? extends V> values) {
		Set<V> oldSet = get(key);
		if (oldSet != null) {
			oldSet.addAll(values);
		} else {
			Set<V> newSet = new HashSet<V>(values);
			put(key, newSet);
		}
	}

    /**
     * Removes the specified value from the set of values assigned to
     * the specified key.
     *
     * @param key Key whose members will have the value removed.
     * @param value Value to remove from the set of members assigned
     * to the key.
     * @return <code>true</code> if the value was in the set of
     * members for the key.
     */
	public boolean removeMember(K key, V value) {
		Set<V> set = get(key);
		if (set != null) {
			return set.remove(value);
		}
		return false;
	}

    /**
     * Returns the set of values for the specified key, or the empty
     * set if there have been none added.  This behavior only differs
     * from the basic {@link #get(Object)} method in that it returns the
     * empty set rather than <code>null</code>.
     */
	public Set<V> getSet(K key) {
		Set<V> result = get(key);
		return result != null ? result : new HashSet<V>(0);
	}
}